﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using A2DFramework.BusinessExceptionService.Exceptions;
using System.IO;
using System.Xml.Linq;

namespace A2DFramework.BusinessExceptionService.Configuration
{
    static class BESConfig
    {
        public static Dictionary<string, Scene> SceneMaps;

        static BESConfig()
        {
            Load();
        }

        public static void Load()
        {
            XElement root = XElement.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "A2D.config"));

            root = root.Element("BusinessExceptionService");
            if (root == null)
                throw new Exception("BusinessExceptionService node not exists");

            //判断是否存在configSource属性，存在则从指定的路径中加载服务配置信息
            //比如从网络共享路径中加载，这样如果分布较多，则可以降低配置的工作量以及减少出错概率
            if (root.Attribute("configSource") != null)
            {
                string configSource = root.Attribute("configSource").Value;

                string filePath = string.Empty;

                if (File.Exists(configSource))
                    filePath = configSource;
                else
                    filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, configSource);

                root = XElement.Load(filePath);
                root = root.Element("BusinessExceptionService");
            }

            var lst = new Dictionary<string, Scene>();
            foreach (var sceneElm in root.Elements("Scene"))
            {
                Scene scene = new Scene();
                scene.SceneName = sceneElm.Attribute("Name").Value;
                scene.EntityTypes = new List<EntityType>();

                foreach (var entityTypeElm in sceneElm.Elements("EntityType"))
                {
                    EntityType entityType = new EntityType();
                    entityType.TargetType = Type.GetType(entityTypeElm.Attribute("Type").Value);
                    entityType.Rules = new List<Rule>();

                    foreach (var ruleElm in entityTypeElm.Elements("Rule"))
                    {
                        Rule rule = new Rule();

                        rule.ErrorMessage = ruleElm.Attribute("ErrorMessage").Value;

                        string failAction = ruleElm.Attribute("FailAction").Value;
                        rule.FailAction = (FailAction)Enum.Parse(typeof(FailAction), failAction);

                        rule.PropertyName = string.Empty;
                        if (ruleElm.Attribute("PropertyName")!=null)
                            rule.PropertyName = ruleElm.Attribute("PropertyName").Value;

                        rule.RuleContent = ruleElm.Value;

                        string ruleType = ruleElm.Attribute("RuleType").Value;
                        rule.RuleType = (RuleType)Enum.Parse(typeof(RuleType), ruleType);

                        if (rule.RuleType == RuleType.ClassValidator)
                            rule.PropertyName = string.Format("*{0}*", entityType.TargetType.Name);

                        entityType.Rules.Add(rule);
                    }
                    scene.EntityTypes.Add(entityType);
                }

                lst.Add(scene.SceneName, scene);
            }
            SceneMaps = lst;
        }
    }
}
